package com.ff.javamonkey.socket;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import java.util.Vector;

import com.ff.javamonkey.socket.message.Message;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.SftpProgressMonitor;

public class SFTPClientConnect implements ClientConnect {
	// Debugging
	private final String TAG = "SFTPClientConnect";
	
	// Connection Variables
	private String hostAddress;
	private static int hostPort = 21;
	
	// Socket status
	private ChannelSftp cSftp;
	private boolean connected = false;
	private String message;
	private int status = 0;
	
	// File read Status
	private int readStatus = 0;
	
	public SFTPClientConnect(String host) {
		this(host, hostPort);
	}
	
	public SFTPClientConnect(String host, int port) {
		this.hostAddress = host;
		SFTPClientConnect.hostPort = port;
	}
	
	public void connect(String user, String pass) throws IOException {
		JSch jsch = new JSch();
		
		try {
			message = "Establishing a connection with " + hostAddress;
			Session session = jsch.getSession(user, hostAddress);
			session.setPassword(pass);
			
			Properties prop = new Properties();
			prop.put("StrictHostKeyChecking", "no");
			
			message = "Attempting to connect.";
			session.setConfig(prop);
			session.connect();
			
			message = "Openning SFTP Channel.";
			Channel channel = session.openChannel("sftp");
			channel.connect();
			
			cSftp = (ChannelSftp) channel;
			setConnected(true);
		} catch (JSchException e) {
			e.printStackTrace();
		}
	}

	public int getFileSize(String fileName) throws IOException {
		SftpATTRS attrs = null;
		try {
			attrs = cSftp.lstat(fileName);
		} catch (SftpException e) {
			throw new IOException("Can't read the file size for " + fileName);
		}
		return (int)attrs.getSize();
	}

	public String getMessage() {
		return message;
	}

	public boolean isConnected() {
		return connected;
	}

	public int getConnectionStatus() {
		return this.status;
	}

	public void setConnectionStatus(int stat) {
		this.status = stat;
	}

	public byte[] getFile(String fileName) throws IOException {
		try {
			SftpProgressMonitor monitor = new ProgressMonitor();
			ByteArrayOutputStream buff = new ByteArrayOutputStream();
			cSftp.get(fileName, buff, monitor);
			return buff.toByteArray();
		}
		catch (SftpException e) {
			e.printStackTrace();
			throw new IOException("Can't get the file " + fileName);
		}
	}

	/**
	 * Given two arguments, fileName, and fileOut, read the file. from fileName to fileOut.
	 */
	public File getFile(String fileName, String fileOut) throws IOException {
		try {
			SftpProgressMonitor mointor = new ProgressMonitor();
			cSftp.get(fileName, fileOut, mointor);
			return null;
		}
		catch (SftpException e) {
			e.printStackTrace();
			throw new IOException("Can't get the file " + fileName);
		}
	}
	
	/**
	 * Given the extension name, get all the file from a given directory.
	 */
	public String[] getFileNames(String directory, String extension) {
		Vector returnMe = new Vector();
		try {
			cSftp.cd(directory);
			returnMe = cSftp.ls(extension);
		} catch (SftpException e) {
			e.printStackTrace();
		}
		String[] returnedString = new String[returnMe.size()];
		int i = 0;
		for (Object o: returnMe) {
			if (o instanceof LsEntry) 
			returnedString[i++] = ((LsEntry)o).getFilename();
		}
		return returnedString;
	}
	
	public void close() throws IOException {
		if (cSftp.isConnected()) cSftp.quit();
		if (!cSftp.isClosed()) cSftp.exit();
	}

	public int getReadStatus() {
		return this.readStatus;
	}

	public void setReadStatus(int stat) {
		this.readStatus = stat;
	}
	
	public void setConnected(boolean connected) {
		this.connected = connected;
		if (this.connected) {
			setConnectionStatus(ClientConnect.CLIENT_CONNECTION_SUCCESSFUL);
		}
	}

	private class ProgressMonitor implements SftpProgressMonitor {
		long count = 0;
		long max = 0;
		private long percent = -1;
		private final String TAG = "SftpProgressMonitor";
		
		public boolean count(long arg0) {
			this.count += arg0;
			if (percent >= this.count*100/max) { return true; }
			percent = this.count*100/max;
			setReadStatus((int)count);
			return true; // test
		}

		public void end() {
		}

		public void init(int arg0, String arg1, String arg2, long arg3) {
			this.max = arg3;
			count = 0;
			percent = -1;
		}
	}

	public void write(Message message) {
		// TODO Auto-generated method stub
		
	}

	public String read() {
		// TODO Auto-generated method stub
		return null;
	}

	public void connect(String host, int port) throws IOException {
		// TODO Auto-generated method stub
		
	}

	public void write(File file) {
		// TODO Auto-generated method stub
		
	}
}